#ifndef MESSAGE_H
#define MESSAGE_H

#include <string>
#include <set>
#include "Folder.h"

class Message
{
    friend class Folder;
    friend void swap(Message &, Message &);
private:
    std::string contents; // 实际消息文本
    std::set<Folder*> folders; // 包含本 Message 的 Folder
    // 拷贝构造函数、拷贝赋值运算符和析构函数所使用的工具函数
    // 将本 Message 添加到指向参数的 Folder 中
    void add_to_Folders(const Message&);
    // 从 folders 中的每个 Folder 中删除本 Message
    void remove_from_Folders();
public:
    // folders 被隐式初始化为空集合
    explicit Message(const std::string &str = " ") : 
                     contents(str) { }
    // 拷贝控制成员，用来管理指向本 Message 的指针
    Message(const Message&); // 拷贝构造函数
    Message& operator=(const Message&); // 拷贝赋值运算符
    Message(Message &&); // 移动构造函数
    Message& operator=(Message &&); // 移动赋值运算符
    ~Message(); // 析构函数
    // 从给定 Folder 集合中添加/删除本 Message
    void save(Folder&);
    void remove(Folder&);
    void addFldr(Folder *);
    void remFldr(Folder *);
    void remove(Folder &);
    void move_Folders(Message *);
};
/**
 * @brief Construct a new Message:: Message object
 *        拷贝构造函数
 * 
 * @param m 
 */
Message::Message(const Message &m) : 
                 contents(m.contents), folders(m.folders)
{
    add_to_Folders(m); // 将本消息添加到指向 m 的 folder 中
}
/**
 * @brief Destroy the Message:: Message object
 * 
 */
Message::~Message( )
{
    remove_from_Folders();
}
/**
 * @brief 拷贝赋值运算符
 * 
 * @param rhs 
 * @return Message& 
 */
Message& Message::operator=(const Message &rhs)
{
    // 通过先删除指针再插入它们来处理自赋值情况
    remove_from_Folders(); // 更新已有 Folder
    contents = rhs.contents; // 从 rhs 拷贝消息内容
    folders = rhs.folders; // 从 rhs 拷贝 Folder 指针
    add_to_Folders(rhs); // 将本 Message 添加到那些 Folder 中
    return *this;
}
/**
 * @brief Construct a new Message:: Message object
 *        移动 folders 并更新 Folder 指针
 * 
 * @param m 
 */
Message::Message(Message &&m) 
    : contents(std::move(m.contents))
{
    move_Folders(&m); 
}
/**
 * @brief 移动赋值运算符
 * 
 * @param rhs 
 * @return Message& 
 */
Message & Message::operator= (Message &&rhs)
{
    if(this != &rhs) // 直接检查自赋值情况
    {
        remove_from_Folders(); // 
        contents = std::move(rhs.contents); // 移动赋值运算符
        move_Folders(&rhs); // 重置 Folders 指向本 Message
    }
    return *this;
}
/**
 * @brief 
 * 
 * @param f 
 */
void Message::save(Folder &f)
{
    folders.insert(&f); // 将给定 Folder 添加到我们的 Folder 列表中
    f.addMsg(this); // 将本 Message 添加到 f 的 Message 集合中
}
/**
 * @brief 
 * 
 * @param f 
 */
void Message::remove(Folder &f)
{
    folders.erase(&f); // 将给定 Folder 从我们的 Folder列表中删除
    f.remMsg(this); // 将本 Message 从 f 的 Message 集合中删除
}
/**
 * @brief 将本 Message 添加到指向 m 的 Folder 中
 * 
 * @param m 
 */
void Message::add_to_Folders(const Message &m)
{
    for(auto f : m.folders) // 对每个包含 m 的 Folder
    {
        f->addMsg(this); // 向该 Folder 添加一个指向本 Message 的指针
    }
}
/**
 * @brief 从对应的 Folder 中删除本 Message
 * 
 */
void Message::remove_from_Folders()
{
    for(auto f : folders) // 对 folders 中每个指针
    {
        f->remMsg(this); // 从该 Folder 中删除本 Message
    }
}
/**
 * @brief 添加给定 Folder
 * 
 * @param f 
 */
void Message::addFldr(Folder *f)
{
    folders.insert(f); 
}
/**
 * @brief 
 * 
 * @param f 
 */
void Message::remFldr(Folder *f)
{
    folders.erase(f);
}
/**
 * @brief 删除给定 Folder
 * 
 * @param f 
 */
void Message::remove(Folder &f)
{
    folders.erase(&f); // 将 Folder 从此 Message 中删除
    f.remMsg(this); // 反向:将 Message 也从此 Folder 中删除
}
/**
 * @brief 
 * 
 * @param lhs 
 * @param rhs 
 */
void swap(Message &lhs, Message &rhs)
{
    // 将每个消息的指针从它原来所在 Folder 中删除
    for(auto f : lhs.folders)
    {
        f->remMsg(&lhs);
    }
    for(auto f : rhs.folders)
    {
        f->remMsg(&rhs);
    }
    // 交换 contents 和 Folder 指针 set
    std::swap(lhs.folders, rhs.folders); // 使用 swap(set&, set&)
    std::swap(lhs.contents, rhs.contents); // 使用 swap(string&, string&)
    // 将每个 Message 的指针添加到它的新 Folder 中
    for(auto f : lhs.folders)
    {
        f->addMsg(&lhs);
    }
    for(auto f : rhs.folders)
    {
        f->addMsg(&rhs);
    }
}
/**
 * @brief 从本 Message 移动 Folder 指针
 * 
 * @param m 
 */
void Message::move_Folders(Message *m)
{
    folders = std::move(m->folders); // 使用 set 的移动赋值运算符
    for(auto f : folders) // 对每个 Folder
    {
        f->remMsg(m); // 从 Folder 中删除旧 Message
        f->addMsg(this); // 将本 Message 添加到 Folder中
    }
    m->folders.clear(); // 确保销毁 m 是无害的。
}
#endif